'''
This example illustrates the basics of building a Graphical User
Interface using fltk.
'''
import sys
#Include the parent directory in the search path so that Python can 
#find pyrwi
sys.path.append("..") 

#Load the nidaqmx library and name it DAQmx so that all functions
#are available as DAQmx.function_name
import nidaqmx as DAQmx
import pyrwi #Load the PyRWI module so we can use it's graphical widgets

#pyFLTK is used to build the actual GUI
#See http://pyfltk.sourceforge.net/docs/CH0_Preface.html for more info
import fltk 

#Load the math library to give us arrays and math functions
import scipy as sp

class LabWindow (fltk.Fl_Window):
    '''
    Here we make our own window class based on the flkt basic window.
    All of our graphical user interface will be specified here.
    '''
    
    def __init__(self, w, h, label):
        '''
        This is the constructor for this class. We will design our
        Interface here.
        '''
        
        #Call the parent constructor
        fltk.Fl_Window.__init__(self, w, h, label)
        
        #--- Menus
        
        #The first menu will be called 'File'. There will be one item
        #in that menu called 'Exit'. If the user selects 'Exit'
        #then the function mnu_quit_cb in this class will be called
        menuitems = (( "&File",              0, 0, 0, fltk.FL_SUBMENU ),
            ( "E&xit", fltk.FL_CTRL + ord('q'), self.mnu_quit_cb ),
            ( None, 0 ),
        #The second menu will be called 'Log', it will have one item in
        #it called 'Save Log'. 'Save Log' will call the mnu_log_save
        #function.
          ( "&Log", 0, 0, 0, fltk.FL_SUBMENU ),
            ( "&Save Log", fltk.FL_CTRL + ord('s'), self.mnu_log_save ),
            ( None, 0 ),

          ( None, 0 )
        )
        m = fltk.Fl_Menu_Bar(0, 0, w, 30) #Create a menu Widget
        m.copy(menuitems) #Assign the menu configuration
        
        #--- Buttons
        #The pyrwi.Fl_Button_Stack makes creating a seris of buttons
        #easy. This stack will start at x=100 pixels (px) and y=50 px.
        #Each button will be 90 px wide and 25 px high.
        #pdy is short for Percent Delta Y, each new button will be 25%
        #of the button height down from the last button. Use pdx
        #to make buttons in a row instead of a column.
        stack = pyrwi.Fl_Button_Stack(10,50,90,25,pdy=0.25)
        
        #The first button will be called "Clear" and when it is clicked
        #the function btn_clear_cb in this class will be called
        stack.addBtn("Clear",self.btn_clear_cb)
        #The second button is called "Add" and calls btn_addData_cb
        stack.addBtn("Add",self.btn_addData_cb)
        #The third button is called "Run" and calls btn_run_cb
        #Note that a different style of button is used here. This
        #button will have a little on/off light
        #Note also that we create a method to store this button object in.
        self.run_btn = stack.addBtn("Run",self.btn_run_cb,"light")
        
        #pyrwi.Fl_Log is a widget that makes logging program activity
        #easy to do. This widget will show at the bottom of the window,
        #be 150px high. Look for self.log later in this code to see
        #how the log is used.
        log_h = 150
        self.log = pyrwi.Fl_Log(0, h-log_h, w, log_h, "Label")
        
        #pyrwi.Fl_Plot is an extention of the PyLab plot that allows
        #rapid real time plotting. Look for self.myPlot later in this
        #code to see how the plot is used.
        self.myPlot = pyrwi.Fl_Plot(110,40, 400,200, "DAQ Reading")
        
    def mnu_quit_cb(self, event) :
        '''
        This function is called when the Exit menu item is selected.
        '''
        #This class is the top window, so hiding this window exits
        #the program.
        self.hide()
    
    def mnu_log_save(self, event) :
        '''
        This function is called when the Save Log menu item is selected.
        '''
        #The log object has its own save method, we just have to tell
        #it the file name to save to
        self.log.save("log.txt")
        
    def btn_run_cb(self, event) :
        '''
        This function is called when the Run button is pressed.
        '''
        #We can inspect the state of the button and find out if it is
        #on or off
        state = self.run_btn.value()
        
        #Make a note of the state in the log
        self.log.note("Pushed! Value is %d" % state)
    
    def btn_clear_cb(self, event):
        '''
        This function is called when the Clear button is pressed.
        '''
        #The log can also record warnings and errors
        self.log.warn("clear something!")
        
        #Erase the current plot
        self.myPlot.clear()
        
    def btn_addData_cb(self, event):
        '''
        This function is called when the Add button is pressed.
        '''
        #Use the SciPy library to make a nice sinewave.
        x = sp.arange(0,1,0.01)
        y = sp.sin(2*sp.pi*x)
        
        #Data can be plotted to the Fl_Plot using the same arguments
        #as the pylab.plot function uses.
        self.myPlot.plot(x,y)
    

if __name__ == "__main__" :
    '''
    This code will only run if I run this file directly. If I load
    this file as a module somewhere else this code will not run
    '''
    #Create a window object
    win = LabWindow(600, 500, "MyWindow")
    
    #Show the window
    win.show(1, sys.argv)

    #Start the event loop and wait for an event (button press or
    #menu item selection.)
    fltk.Fl.run()
